package com.sk.orm;

import com.sk.orm.support.Criteria;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * CommonDao接口定义
 *
 * @author smy
 * {@code @date} 2022/10/26
 */
public interface CommonDao {
    /**
     * 新增。
     * 如果ID数据库自生成，保存时ID需为null，返回值有数据库ID。
     *
     * @param t   业务数据
     * @param <T> 数据泛型约束
     * @return 数据库数据
     */
    <T> T add(T t);

    /**
     * 批量新增。
     *
     * @param list 对象集合
     * @see #add(Object)
     */
    default void add(Collection<?> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        list.forEach(this::add);
    }

    /**
     * 保存更新。
     * ID存在，其他字段覆盖原始数据。
     * ID为null且ID数据库生成，可以保存数据。
     *
     * @param t   业务数据
     * @param <T> 数据泛型约束
     * @return 数据库数据
     */
    <T> T update(T t);

    /**
     * 批量保存更新。
     *
     * @param list 对象集合
     * @see #update(Object)
     */
    default void update(Collection<?> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        list.forEach(this::update);
    }

    /**
     * 删除对象
     *
     * @param o 删除对象
     */
    void delete(Object o);

    /**
     * 批量删除
     *
     * @param list 删除对象集合
     */
    default void delete(Collection<?> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        list.forEach(this::delete);
    }

    /**
     * 主键删除
     *
     * @param e  数据类型
     * @param id 数据主键值
     */
    default void delete(Class<?> e, Object id) {
        Object o = find(e, id);
        if (o != null) {
            delete(o);
        }
    }

    /**
     * 主键批量删除
     *
     * @param e   数据类型
     * @param ids 数据主键列表
     */
    default void delete(Class<?> e, Collection<?> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }
        ids.forEach(id -> delete(e, id));
    }

    /**
     * 查询单数据 by 主键
     *
     * @param e   数据类型
     * @param id  数据主键值
     * @param <T> 泛型约束
     * @return 数据库数据
     */
    <T> T find(Class<T> e, Object id);

    /**
     * 查询单数据  by 组合查询条件
     *
     * @param c   组合查询条件
     * @param <T> 泛型约束
     * @return 数据
     */
    default <T> T find(Criteria<T> c) {
        c.limit(1);
        List<T> list = list(c);
        return list.isEmpty() ? null : list.get(0);
    }

    /**
     * 查询对象列表。
     *
     * @param c   组合查询条件
     * @param <T> 对象泛型约束
     * @return 对象列表
     */
    <T> List<T> list(Criteria<T> c);

    /**
     * 统计计数
     *
     * @param c   组合查询条件
     * @param <T> 对象泛型约束
     * @return 数量
     */
    <T> long count(Criteria<T> c);

    /**
     * 分页查询
     *
     * @param c   组合查询条件
     * @param <T> 对象泛型约束
     * @return 分页查询结果
     */
    <T> PageResult<T> page(Criteria<T> c);

    /**
     * jsql 执行语句
     *
     * @param jsql  jsql
     * @param param 参数列表
     * @return 执行成功数量
     */
    int execute(String jsql, Map<String, Object> param);

    /**
     * jsql查询
     *
     * @param jsql     jsql
     * @param param    参数
     * @param function 结果转换方法
     * @param <T>      返回结果泛型约束
     * @return 查询结果
     */
    <T> List<T> select(String jsql, Map<String, Object> param, Function<Object, T> function);

    /**
     * jsql查询
     *
     * @param jsql     jsql
     * @param function 结果转换方法
     * @param <T>      返回结果泛型约束
     * @return 查询结果
     */
    default <T> List<T> select(String jsql, Function<Object, T> function) {
        return select(jsql, Collections.emptyMap(), function);
    }

    /**
     * jsql查询
     *
     * @param jsql     jsql
     * @param param    参数
     * @param function 结果转换方法
     * @param <T>      返回结果泛型约束
     * @return 查询结果
     */
    default <T> T selectOne(String jsql, Map<String, Object> param, Function<Object, T> function) {
        List<T> list = select(jsql, param, function);
        return list.isEmpty() ? null : list.get(0);
    }

    /**
     * jsql查询
     *
     * @param jsql     jsql
     * @param function 结果转换方法
     * @param <T>      返回结果泛型约束
     * @return 查询结果
     */
    default <T> T selectOne(String jsql, Function<Object, T> function) {
        return selectOne(jsql, Collections.emptyMap(), function);
    }


    /**
     * sql执行语句
     *
     * @param sql   sql
     * @param param 参数
     * @return 执行条数
     */
    int executeSql(String sql, Map<String, Object> param);

    /**
     * sql查询
     *
     * @param sql      sql
     * @param param    参数
     * @param function 结果转换方法
     * @param <T>      返回结果泛型约束
     * @return 查询结果
     */
    <T> List<T> selectSql(String sql, Map<String, Object> param, Function<Object, T> function);

    /**
     * sql查询
     *
     * @param sql      sql
     * @param function 结果转换方法
     * @param <T>      返回结果泛型约束
     * @return 查询结果
     */
    default <T> List<T> selectSql(String sql, Function<Object, T> function) {
        return selectSql(sql, Collections.emptyMap(), function);
    }

    /**
     * sql查询
     *
     * @param sql      sql
     * @param param    参数
     * @param function 结果转换方法
     * @param <T>      返回结果泛型约束
     * @return 查询结果
     */
    default <T> T selectSqlOne(String sql, Map<String, Object> param, Function<Object, T> function) {
        List<T> list = selectSql(sql, param, function);
        return list.isEmpty() ? null : list.get(0);
    }

    /**
     * sql查询
     *
     * @param sql      sql
     * @param function 结果转换方法
     * @param <T>      返回结果泛型约束
     * @return 查询结果
     */
    default <T> T selectSqlOne(String sql, Function<Object, T> function) {
        return selectSqlOne(sql, Collections.emptyMap(), function);
    }

}
